home *** CD-ROM | disk | FTP | other *** search
/ PC/CD Gamer UK 120 / CD Gamer Issue 120 (March 2003) (Disc 2).ISO / mods / Q2_Codered / codeRED1_0.exe / Data1.cab / q_shared.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-08-13  |  26.4 KB  |  1,420 lines

  1. /*
  2. Copyright (C) 1997-2001 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. #include "q_shared.h"
  21.  
  22. #define DEG2RAD( a ) ( a * M_PI ) / 180.0F
  23.  
  24. vec3_t vec3_origin = {0,0,0};
  25.  
  26. //============================================================================
  27.  
  28. #ifdef _WIN32
  29. #pragma optimize( "", off )
  30. #endif
  31.  
  32. void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees )
  33. {
  34.     float    m[3][3];
  35.     float    im[3][3];
  36.     float    zrot[3][3];
  37.     float    tmpmat[3][3];
  38.     float    rot[3][3];
  39.     int    i;
  40.     vec3_t vr, vup, vf;
  41.  
  42.     vf[0] = dir[0];
  43.     vf[1] = dir[1];
  44.     vf[2] = dir[2];
  45.  
  46.     PerpendicularVector( vr, dir );
  47.     CrossProduct( vr, vf, vup );
  48.  
  49.     m[0][0] = vr[0];
  50.     m[1][0] = vr[1];
  51.     m[2][0] = vr[2];
  52.  
  53.     m[0][1] = vup[0];
  54.     m[1][1] = vup[1];
  55.     m[2][1] = vup[2];
  56.  
  57.     m[0][2] = vf[0];
  58.     m[1][2] = vf[1];
  59.     m[2][2] = vf[2];
  60.  
  61.     memcpy( im, m, sizeof( im ) );
  62.  
  63.     im[0][1] = m[1][0];
  64.     im[0][2] = m[2][0];
  65.     im[1][0] = m[0][1];
  66.     im[1][2] = m[2][1];
  67.     im[2][0] = m[0][2];
  68.     im[2][1] = m[1][2];
  69.  
  70.     memset( zrot, 0, sizeof( zrot ) );
  71.     zrot[0][0] = zrot[1][1] = zrot[2][2] = 1.0F;
  72.  
  73.     zrot[0][0] = cos( DEG2RAD( degrees ) );
  74.     zrot[0][1] = sin( DEG2RAD( degrees ) );
  75.     zrot[1][0] = -sin( DEG2RAD( degrees ) );
  76.     zrot[1][1] = cos( DEG2RAD( degrees ) );
  77.  
  78.     R_ConcatRotations( m, zrot, tmpmat );
  79.     R_ConcatRotations( tmpmat, im, rot );
  80.  
  81.     for ( i = 0; i < 3; i++ )
  82.     {
  83.         dst[i] = rot[i][0] * point[0] + rot[i][1] * point[1] + rot[i][2] * point[2];
  84.     }
  85. }
  86.  
  87. #ifdef _WIN32
  88. #pragma optimize( "", on )
  89. #endif
  90.  
  91.  
  92.  
  93. void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
  94. {
  95.     float        angle;
  96.     static float        sr, sp, sy, cr, cp, cy;
  97.     // static to help MS compiler fp bugs
  98.  
  99.     angle = angles[YAW] * (M_PI*2 / 360);
  100.     sy = sin(angle);
  101.     cy = cos(angle);
  102.     angle = angles[PITCH] * (M_PI*2 / 360);
  103.     sp = sin(angle);
  104.     cp = cos(angle);
  105.     angle = angles[ROLL] * (M_PI*2 / 360);
  106.     sr = sin(angle);
  107.     cr = cos(angle);
  108.  
  109.     if (forward)
  110.     {
  111.         forward[0] = cp*cy;
  112.         forward[1] = cp*sy;
  113.         forward[2] = -sp;
  114.     }
  115.     if (right)
  116.     {
  117.         right[0] = (-1*sr*sp*cy+-1*cr*-sy);
  118.         right[1] = (-1*sr*sp*sy+-1*cr*cy);
  119.         right[2] = -1*sr*cp;
  120.     }
  121.     if (up)
  122.     {
  123.         up[0] = (cr*sp*cy+-sr*-sy);
  124.         up[1] = (cr*sp*sy+-sr*cy);
  125.         up[2] = cr*cp;
  126.     }
  127. }
  128.  
  129.  
  130. void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal )
  131. {
  132.     float d;
  133.     vec3_t n;
  134.     float inv_denom;
  135.  
  136.     inv_denom = 1.0F / DotProduct( normal, normal );
  137.  
  138.     d = DotProduct( normal, p ) * inv_denom;
  139.  
  140.     n[0] = normal[0] * inv_denom;
  141.     n[1] = normal[1] * inv_denom;
  142.     n[2] = normal[2] * inv_denom;
  143.  
  144.     dst[0] = p[0] - d * n[0];
  145.     dst[1] = p[1] - d * n[1];
  146.     dst[2] = p[2] - d * n[2];
  147. }
  148.  
  149. /*
  150. ** assumes "src" is normalized
  151. */
  152. void PerpendicularVector( vec3_t dst, const vec3_t src )
  153. {
  154.     int    pos;
  155.     int i;
  156.     float minelem = 1.0F;
  157.     vec3_t tempvec;
  158.  
  159.     /*
  160.     ** find the smallest magnitude axially aligned vector
  161.     */
  162.     for ( pos = 0, i = 0; i < 3; i++ )
  163.     {
  164.         if ( fabs( src[i] ) < minelem )
  165.         {
  166.             pos = i;
  167.             minelem = fabs( src[i] );
  168.         }
  169.     }
  170.     tempvec[0] = tempvec[1] = tempvec[2] = 0.0F;
  171.     tempvec[pos] = 1.0F;
  172.  
  173.     /*
  174.     ** project the point onto the plane defined by src
  175.     */
  176.     ProjectPointOnPlane( dst, tempvec, src );
  177.  
  178.     /*
  179.     ** normalize the result
  180.     */
  181.     VectorNormalize( dst );
  182. }
  183.  
  184.  
  185.  
  186. /*
  187. ================
  188. R_ConcatRotations
  189. ================
  190. */
  191. void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3])
  192. {
  193.     out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
  194.                 in1[0][2] * in2[2][0];
  195.     out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
  196.                 in1[0][2] * in2[2][1];
  197.     out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
  198.                 in1[0][2] * in2[2][2];
  199.     out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
  200.                 in1[1][2] * in2[2][0];
  201.     out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
  202.                 in1[1][2] * in2[2][1];
  203.     out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
  204.                 in1[1][2] * in2[2][2];
  205.     out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
  206.                 in1[2][2] * in2[2][0];
  207.     out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
  208.                 in1[2][2] * in2[2][1];
  209.     out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
  210.                 in1[2][2] * in2[2][2];
  211. }
  212.  
  213.  
  214. /*
  215. ================
  216. R_ConcatTransforms
  217. ================
  218. */
  219. void R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4])
  220. {
  221.     out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
  222.                 in1[0][2] * in2[2][0];
  223.     out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
  224.                 in1[0][2] * in2[2][1];
  225.     out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
  226.                 in1[0][2] * in2[2][2];
  227.     out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] +
  228.                 in1[0][2] * in2[2][3] + in1[0][3];
  229.     out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
  230.                 in1[1][2] * in2[2][0];
  231.     out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
  232.                 in1[1][2] * in2[2][1];
  233.     out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
  234.                 in1[1][2] * in2[2][2];
  235.     out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] +
  236.                 in1[1][2] * in2[2][3] + in1[1][3];
  237.     out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
  238.                 in1[2][2] * in2[2][0];
  239.     out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
  240.                 in1[2][2] * in2[2][1];
  241.     out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
  242.                 in1[2][2] * in2[2][2];
  243.     out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] +
  244.                 in1[2][2] * in2[2][3] + in1[2][3];
  245. }
  246.  
  247.  
  248. //============================================================================
  249.  
  250.  
  251. float Q_fabs (float f)
  252. {
  253. #if 0
  254.     if (f >= 0)
  255.         return f;
  256.     return -f;
  257. #else
  258.     int tmp = * ( int * ) &f;
  259.     tmp &= 0x7FFFFFFF;
  260.     return * ( float * ) &tmp;
  261. #endif
  262. }
  263.  
  264. #if defined _M_IX86 && !defined C_ONLY
  265. #pragma warning (disable:4035)
  266. __declspec( naked ) long Q_ftol( float f )
  267. {
  268.     static int tmp;
  269.     __asm fld dword ptr [esp+4]
  270.     __asm fistp tmp
  271.     __asm mov eax, tmp
  272.     __asm ret
  273. }
  274. #pragma warning (default:4035)
  275. #endif
  276.  
  277. /*
  278. ===============
  279. LerpAngle
  280.  
  281. ===============
  282. */
  283. float LerpAngle (float a2, float a1, float frac)
  284. {
  285.     if (a1 - a2 > 180)
  286.         a1 -= 360;
  287.     if (a1 - a2 < -180)
  288.         a1 += 360;
  289.     return a2 + frac * (a1 - a2);
  290. }
  291.  
  292.  
  293. float    anglemod(float a)
  294. {
  295. #if 0
  296.     if (a >= 0)
  297.         a -= 360*(int)(a/360);
  298.     else
  299.         a += 360*( 1 + (int)(-a/360) );
  300. #endif
  301.     a = (360.0/65536) * ((int)(a*(65536/360.0)) & 65535);
  302.     return a;
  303. }
  304.  
  305.     int        i;
  306.     vec3_t    corners[2];
  307.  
  308.  
  309. // this is the slow, general version
  310. int BoxOnPlaneSide2 (vec3_t emins, vec3_t emaxs, struct cplane_s *p)
  311. {
  312.     int        i;
  313.     float    dist1, dist2;
  314.     int        sides;
  315.     vec3_t    corners[2];
  316.  
  317.     for (i=0 ; i<3 ; i++)
  318.     {
  319.         if (p->normal[i] < 0)
  320.         {
  321.             corners[0][i] = emins[i];
  322.             corners[1][i] = emaxs[i];
  323.         }
  324.         else
  325.         {
  326.             corners[1][i] = emins[i];
  327.             corners[0][i] = emaxs[i];
  328.         }
  329.     }
  330.     dist1 = DotProduct (p->normal, corners[0]) - p->dist;
  331.     dist2 = DotProduct (p->normal, corners[1]) - p->dist;
  332.     sides = 0;
  333.     if (dist1 >= 0)
  334.         sides = 1;
  335.     if (dist2 < 0)
  336.         sides |= 2;
  337.  
  338.     return sides;
  339. }
  340.  
  341. /*
  342. ==================
  343. BoxOnPlaneSide
  344.  
  345. Returns 1, 2, or 1 + 2
  346. ==================
  347. */
  348. #if !id386 || defined __linux__
  349. int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, struct cplane_s *p)
  350. {
  351.     float    dist1, dist2;
  352.     int        sides;
  353.  
  354. // fast axial cases
  355.     if (p->type < 3)
  356.     {
  357.         if (p->dist <= emins[p->type])
  358.             return 1;
  359.         if (p->dist >= emaxs[p->type])
  360.             return 2;
  361.         return 3;
  362.     }
  363.     
  364. // general case
  365.     switch (p->signbits)
  366.     {
  367.     case 0:
  368. dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
  369. dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
  370.         break;
  371.     case 1:
  372. dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
  373. dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
  374.         break;
  375.     case 2:
  376. dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
  377. dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
  378.         break;
  379.     case 3:
  380. dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
  381. dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
  382.         break;
  383.     case 4:
  384. dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
  385. dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
  386.         break;
  387.     case 5:
  388. dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
  389. dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
  390.         break;
  391.     case 6:
  392. dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
  393. dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
  394.         break;
  395.     case 7:
  396. dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
  397. dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
  398.         break;
  399.     default:
  400.         dist1 = dist2 = 0;        // shut up compiler
  401.         assert( 0 );
  402.         break;
  403.     }
  404.  
  405.     sides = 0;
  406.     if (dist1 >= p->dist)
  407.         sides = 1;
  408.     if (dist2 < p->dist)
  409.         sides |= 2;
  410.  
  411.     assert( sides != 0 );
  412.  
  413.     return sides;
  414. }
  415. #else
  416. #pragma warning( disable: 4035 )
  417.  
  418. __declspec( naked ) int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, struct cplane_s *p)
  419. {
  420.     static int bops_initialized;
  421.     static int Ljmptab[8];
  422.  
  423.     __asm {
  424.  
  425.         push ebx
  426.             
  427.         cmp bops_initialized, 1
  428.         je  initialized
  429.         mov bops_initialized, 1
  430.         
  431.         mov Ljmptab[0*4], offset Lcase0
  432.         mov Ljmptab[1*4], offset Lcase1
  433.         mov Ljmptab[2*4], offset Lcase2
  434.         mov Ljmptab[3*4], offset Lcase3
  435.         mov Ljmptab[4*4], offset Lcase4
  436.         mov Ljmptab[5*4], offset Lcase5
  437.         mov Ljmptab[6*4], offset Lcase6
  438.         mov Ljmptab[7*4], offset Lcase7
  439.             
  440. initialized:
  441.  
  442.         mov edx,ds:dword ptr[4+12+esp]
  443.         mov ecx,ds:dword ptr[4+4+esp]
  444.         xor eax,eax
  445.         mov ebx,ds:dword ptr[4+8+esp]
  446.         mov al,ds:byte ptr[17+edx]
  447.         cmp al,8
  448.         jge Lerror
  449.         fld ds:dword ptr[0+edx]
  450.         fld st(0)
  451.         jmp dword ptr[Ljmptab+eax*4]
  452. Lcase0:
  453.         fmul ds:dword ptr[ebx]
  454.         fld ds:dword ptr[0+4+edx]
  455.         fxch st(2)
  456.         fmul ds:dword ptr[ecx]
  457.         fxch st(2)
  458.         fld st(0)
  459.         fmul ds:dword ptr[4+ebx]
  460.         fld ds:dword ptr[0+8+edx]
  461.         fxch st(2)
  462.         fmul ds:dword ptr[4+ecx]
  463.         fxch st(2)
  464.         fld st(0)
  465.         fmul ds:dword ptr[8+ebx]
  466.         fxch st(5)
  467.         faddp st(3),st(0)
  468.         fmul ds:dword ptr[8+ecx]
  469.         fxch st(1)
  470.         faddp st(3),st(0)
  471.         fxch st(3)
  472.         faddp st(2),st(0)
  473.         jmp LSetSides
  474. Lcase1:
  475.         fmul ds:dword ptr[ecx]
  476.         fld ds:dword ptr[0+4+edx]
  477.         fxch st(2)
  478.         fmul ds:dword ptr[ebx]
  479.         fxch st(2)
  480.         fld st(0)
  481.         fmul ds:dword ptr[4+ebx]
  482.         fld ds:dword ptr[0+8+edx]
  483.         fxch st(2)
  484.         fmul ds:dword ptr[4+ecx]
  485.         fxch st(2)
  486.         fld st(0)
  487.         fmul ds:dword ptr[8+ebx]
  488.         fxch st(5)
  489.         faddp st(3),st(0)
  490.         fmul ds:dword ptr[8+ecx]
  491.         fxch st(1)
  492.         faddp st(3),st(0)
  493.         fxch st(3)
  494.         faddp st(2),st(0)
  495.         jmp LSetSides
  496. Lcase2:
  497.         fmul ds:dword ptr[ebx]
  498.         fld ds:dword ptr[0+4+edx]
  499.         fxch st(2)
  500.         fmul ds:dword ptr[ecx]
  501.         fxch st(2)
  502.         fld st(0)
  503.         fmul ds:dword ptr[4+ecx]
  504.         fld ds:dword ptr[0+8+edx]
  505.         fxch st(2)
  506.         fmul ds:dword ptr[4+ebx]
  507.         fxch st(2)
  508.         fld st(0)
  509.         fmul ds:dword ptr[8+ebx]
  510.         fxch st(5)
  511.         faddp st(3),st(0)
  512.         fmul ds:dword ptr[8+ecx]
  513.         fxch st(1)
  514.         faddp st(3),st(0)
  515.         fxch st(3)
  516.         faddp st(2),st(0)
  517.         jmp LSetSides
  518. Lcase3:
  519.         fmul ds:dword ptr[ecx]
  520.         fld ds:dword ptr[0+4+edx]
  521.         fxch st(2)
  522.         fmul ds:dword ptr[ebx]
  523.         fxch st(2)
  524.         fld st(0)
  525.         fmul ds:dword ptr[4+ecx]
  526.         fld ds:dword ptr[0+8+edx]
  527.         fxch st(2)
  528.         fmul ds:dword ptr[4+ebx]
  529.         fxch st(2)
  530.         fld st(0)
  531.         fmul ds:dword ptr[8+ebx]
  532.         fxch st(5)
  533.         faddp st(3),st(0)
  534.         fmul ds:dword ptr[8+ecx]
  535.         fxch st(1)
  536.         faddp st(3),st(0)
  537.         fxch st(3)
  538.         faddp st(2),st(0)
  539.         jmp LSetSides
  540. Lcase4:
  541.         fmul ds:dword ptr[ebx]
  542.         fld ds:dword ptr[0+4+edx]
  543.         fxch st(2)
  544.         fmul ds:dword ptr[ecx]
  545.         fxch st(2)
  546.         fld st(0)
  547.         fmul ds:dword ptr[4+ebx]
  548.         fld ds:dword ptr[0+8+edx]
  549.         fxch st(2)
  550.         fmul ds:dword ptr[4+ecx]
  551.         fxch st(2)
  552.         fld st(0)
  553.         fmul ds:dword ptr[8+ecx]
  554.         fxch st(5)
  555.         faddp st(3),st(0)
  556.         fmul ds:dword ptr[8+ebx]
  557.         fxch st(1)
  558.         faddp st(3),st(0)
  559.         fxch st(3)
  560.         faddp st(2),st(0)
  561.         jmp LSetSides
  562. Lcase5:
  563.         fmul ds:dword ptr[ecx]
  564.         fld ds:dword ptr[0+4+edx]
  565.         fxch st(2)
  566.         fmul ds:dword ptr[ebx]
  567.         fxch st(2)
  568.         fld st(0)
  569.         fmul ds:dword ptr[4+ebx]
  570.         fld ds:dword ptr[0+8+edx]
  571.         fxch st(2)
  572.         fmul ds:dword ptr[4+ecx]
  573.         fxch st(2)
  574.         fld st(0)
  575.         fmul ds:dword ptr[8+ecx]
  576.         fxch st(5)
  577.         faddp st(3),st(0)
  578.         fmul ds:dword ptr[8+ebx]
  579.         fxch st(1)
  580.         faddp st(3),st(0)
  581.         fxch st(3)
  582.         faddp st(2),st(0)
  583.         jmp LSetSides
  584. Lcase6:
  585.         fmul ds:dword ptr[ebx]
  586.         fld ds:dword ptr[0+4+edx]
  587.         fxch st(2)
  588.         fmul ds:dword ptr[ecx]
  589.         fxch st(2)
  590.         fld st(0)
  591.         fmul ds:dword ptr[4+ecx]
  592.         fld ds:dword ptr[0+8+edx]
  593.         fxch st(2)
  594.         fmul ds:dword ptr[4+ebx]
  595.         fxch st(2)
  596.         fld st(0)
  597.         fmul ds:dword ptr[8+ecx]
  598.         fxch st(5)
  599.         faddp st(3),st(0)
  600.         fmul ds:dword ptr[8+ebx]
  601.         fxch st(1)
  602.         faddp st(3),st(0)
  603.         fxch st(3)
  604.         faddp st(2),st(0)
  605.         jmp LSetSides
  606. Lcase7:
  607.         fmul ds:dword ptr[ecx]
  608.         fld ds:dword ptr[0+4+edx]
  609.         fxch st(2)
  610.         fmul ds:dword ptr[ebx]
  611.         fxch st(2)
  612.         fld st(0)
  613.         fmul ds:dword ptr[4+ecx]
  614.         fld ds:dword ptr[0+8+edx]
  615.         fxch st(2)
  616.         fmul ds:dword ptr[4+ebx]
  617.         fxch st(2)
  618.         fld st(0)
  619.         fmul ds:dword ptr[8+ecx]
  620.         fxch st(5)
  621.         faddp st(3),st(0)
  622.         fmul ds:dword ptr[8+ebx]
  623.         fxch st(1)
  624.         faddp st(3),st(0)
  625.         fxch st(3)
  626.         faddp st(2),st(0)
  627. LSetSides:
  628.         faddp st(2),st(0)
  629.         fcomp ds:dword ptr[12+edx]
  630.         xor ecx,ecx
  631.         fnstsw ax
  632.         fcomp ds:dword ptr[12+edx]
  633.         and ah,1
  634.         xor ah,1
  635.         add cl,ah
  636.         fnstsw ax
  637.         and ah,1
  638.         add ah,ah
  639.         add cl,ah
  640.         pop ebx
  641.         mov eax,ecx
  642.         ret
  643. Lerror:
  644.         int 3
  645.     }
  646. }
  647. #pragma warning( default: 4035 )
  648. #endif
  649.  
  650. void ClearBounds (vec3_t mins, vec3_t maxs)
  651. {
  652.     mins[0] = mins[1] = mins[2] = 99999;
  653.     maxs[0] = maxs[1] = maxs[2] = -99999;
  654. }
  655.  
  656. void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs)
  657. {
  658.     int        i;
  659.     vec_t    val;
  660.  
  661.     for (i=0 ; i<3 ; i++)
  662.     {
  663.         val = v[i];
  664.         if (val < mins[i])
  665.             mins[i] = val;
  666.         if (val > maxs[i])
  667.             maxs[i] = val;
  668.     }
  669. }
  670.  
  671.  
  672. int VectorCompare (vec3_t v1, vec3_t v2)
  673. {
  674.     if (v1[0] != v2[0] || v1[1] != v2[1] || v1[2] != v2[2])
  675.             return 0;
  676.             
  677.     return 1;
  678. }
  679.  
  680.  
  681. vec_t VectorNormalize (vec3_t v)
  682. {
  683.     float    length, ilength;
  684.  
  685.     length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
  686.     length = sqrt (length);        // FIXME
  687.  
  688.     if (length)
  689.     {
  690.         ilength = 1/length;
  691.         v[0] *= ilength;
  692.         v[1] *= ilength;
  693.         v[2] *= ilength;
  694.     }
  695.         
  696.     return length;
  697.  
  698. }
  699.  
  700. vec_t VectorNormalize2 (vec3_t v, vec3_t out)
  701. {
  702.     float    length, ilength;
  703.  
  704.     length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
  705.     length = sqrt (length);        // FIXME
  706.  
  707.     if (length)
  708.     {
  709.         ilength = 1/length;
  710.         out[0] = v[0]*ilength;
  711.         out[1] = v[1]*ilength;
  712.         out[2] = v[2]*ilength;
  713.     }
  714.         
  715.     return length;
  716.  
  717. }
  718.  
  719. void VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc)
  720. {
  721.     vecc[0] = veca[0] + scale*vecb[0];
  722.     vecc[1] = veca[1] + scale*vecb[1];
  723.     vecc[2] = veca[2] + scale*vecb[2];
  724. }
  725.  
  726.  
  727. vec_t _DotProduct (vec3_t v1, vec3_t v2)
  728. {
  729.     return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
  730. }
  731.  
  732. void _VectorSubtract (vec3_t veca, vec3_t vecb, vec3_t out)
  733. {
  734.     out[0] = veca[0]-vecb[0];
  735.     out[1] = veca[1]-vecb[1];
  736.     out[2] = veca[2]-vecb[2];
  737. }
  738.  
  739. void _VectorAdd (vec3_t veca, vec3_t vecb, vec3_t out)
  740. {
  741.     out[0] = veca[0]+vecb[0];
  742.     out[1] = veca[1]+vecb[1];
  743.     out[2] = veca[2]+vecb[2];
  744. }
  745.  
  746. void _VectorCopy (vec3_t in, vec3_t out)
  747. {
  748.     out[0] = in[0];
  749.     out[1] = in[1];
  750.     out[2] = in[2];
  751. }
  752.  
  753. void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross)
  754. {
  755.     cross[0] = v1[1]*v2[2] - v1[2]*v2[1];
  756.     cross[1] = v1[2]*v2[0] - v1[0]*v2[2];
  757.     cross[2] = v1[0]*v2[1] - v1[1]*v2[0];
  758. }
  759.  
  760. double sqrt(double x);
  761.  
  762. vec_t VectorLength(vec3_t v)
  763. {
  764.     int        i;
  765.     float    length;
  766.     
  767.     length = 0;
  768.     for (i=0 ; i< 3 ; i++)
  769.         length += v[i]*v[i];
  770.     length = sqrt (length);        // FIXME
  771.  
  772.     return length;
  773. }
  774.  
  775. void VectorInverse (vec3_t v)
  776. {
  777.     v[0] = -v[0];
  778.     v[1] = -v[1];
  779.     v[2] = -v[2];
  780. }
  781.  
  782. void VectorScale (vec3_t in, vec_t scale, vec3_t out)
  783. {
  784.     out[0] = in[0]*scale;
  785.     out[1] = in[1]*scale;
  786.     out[2] = in[2]*scale;
  787. }
  788.  
  789.  
  790. int Q_log2(int val)
  791. {
  792.     int answer=0;
  793.     while (val>>=1)
  794.         answer++;
  795.     return answer;
  796. }
  797.  
  798.  
  799.  
  800. //====================================================================================
  801.  
  802. /*
  803. ============
  804. COM_SkipPath
  805. ============
  806. */
  807. char *COM_SkipPath (char *pathname)
  808. {
  809.     char    *last;
  810.     
  811.     last = pathname;
  812.     while (*pathname)
  813.     {
  814.         if (*pathname=='/')
  815.             last = pathname+1;
  816.         pathname++;
  817.     }
  818.     return last;
  819. }
  820.  
  821. /*
  822. ============
  823. COM_StripExtension
  824. ============
  825. */
  826. void COM_StripExtension (char *in, char *out)
  827. {
  828.     while (*in && *in != '.')
  829.         *out++ = *in++;
  830.     *out = 0;
  831. }
  832.  
  833. /*
  834. ============
  835. COM_FileExtension
  836. ============
  837. */
  838. char *COM_FileExtension (char *in)
  839. {
  840.     static char exten[8];
  841.     int        i;
  842.  
  843.     while (*in && *in != '.')
  844.         in++;
  845.     if (!*in)
  846.         return "";
  847.     in++;
  848.     for (i=0 ; i<7 && *in ; i++,in++)
  849.         exten[i] = *in;
  850.     exten[i] = 0;
  851.     return exten;
  852. }
  853.  
  854. /*
  855. ============
  856. COM_FileBase
  857. ============
  858. */
  859. void COM_FileBase (char *in, char *out)
  860. {
  861.     char *s, *s2;
  862.     
  863.     s = in + strlen(in) - 1;
  864.     
  865.     while (s != in && *s != '.')
  866.         s--;
  867.     
  868.     for (s2 = s ; s2 != in && *s2 != '/' ; s2--)
  869.     ;
  870.     
  871.     if (s-s2 < 2)
  872.         out[0] = 0;
  873.     else
  874.     {
  875.         s--;
  876.         strncpy (out,s2+1, s-s2);
  877.         out[s-s2] = 0;
  878.     }
  879. }
  880.  
  881. /*
  882. ============
  883. COM_FilePath
  884.  
  885. Returns the path up to, but not including the last /
  886. ============
  887. */
  888. void COM_FilePath (char *in, char *out)
  889. {
  890.     char *s;
  891.     
  892.     s = in + strlen(in) - 1;
  893.     
  894.     while (s != in && *s != '/')
  895.         s--;
  896.  
  897.     strncpy (out,in, s-in);
  898.     out[s-in] = 0;
  899. }
  900.  
  901.  
  902. /*
  903. ==================
  904. COM_DefaultExtension
  905. ==================
  906. */
  907. void COM_DefaultExtension (char *path, char *extension)
  908. {
  909.     char    *src;
  910. //
  911. // if path doesn't have a .EXT, append extension
  912. // (extension should include the .)
  913. //
  914.     src = path + strlen(path) - 1;
  915.  
  916.     while (*src != '/' && src != path)
  917.     {
  918.         if (*src == '.')
  919.             return;                 // it has an extension
  920.         src--;
  921.     }
  922.  
  923.     strcat (path, extension);
  924. }
  925.  
  926. /*
  927. ============================================================================
  928.  
  929.                     BYTE ORDER FUNCTIONS
  930.  
  931. ============================================================================
  932. */
  933.  
  934. qboolean    bigendien;
  935.  
  936. // can't just use function pointers, or dll linkage can
  937. // mess up when qcommon is included in multiple places
  938. short    (*_BigShort) (short l);
  939. short    (*_LittleShort) (short l);
  940. int        (*_BigLong) (int l);
  941. int        (*_LittleLong) (int l);
  942. float    (*_BigFloat) (float l);
  943. float    (*_LittleFloat) (float l);
  944.  
  945. short    BigShort(short l){return _BigShort(l);}
  946. short    LittleShort(short l) {return _LittleShort(l);}
  947. int        BigLong (int l) {return _BigLong(l);}
  948. int        LittleLong (int l) {return _LittleLong(l);}
  949. float    BigFloat (float l) {return _BigFloat(l);}
  950. float    LittleFloat (float l) {return _LittleFloat(l);}
  951.  
  952. short   ShortSwap (short l)
  953. {
  954.     byte    b1,b2;
  955.  
  956.     b1 = l&255;
  957.     b2 = (l>>8)&255;
  958.  
  959.     return (b1<<8) + b2;
  960. }
  961.  
  962. short    ShortNoSwap (short l)
  963. {
  964.     return l;
  965. }
  966.  
  967. int    LongSwap (int l)
  968. {
  969.     byte    b1,b2,b3,b4;
  970.  
  971.     b1 = l&255;
  972.     b2 = (l>>8)&255;
  973.     b3 = (l>>16)&255;
  974.     b4 = (l>>24)&255;
  975.  
  976.     return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
  977. }
  978.  
  979. int    LongNoSwap (int l)
  980. {
  981.     return l;
  982. }
  983.  
  984. float FloatSwap (float f)
  985. {
  986.     union
  987.     {
  988.         float    f;
  989.         byte    b[4];
  990.     } dat1, dat2;
  991.     
  992.     
  993.     dat1.f = f;
  994.     dat2.b[0] = dat1.b[3];
  995.     dat2.b[1] = dat1.b[2];
  996.     dat2.b[2] = dat1.b[1];
  997.     dat2.b[3] = dat1.b[0];
  998.     return dat2.f;
  999. }
  1000.  
  1001. float FloatNoSwap (float f)
  1002. {
  1003.     return f;
  1004. }
  1005.  
  1006. /*
  1007. ================
  1008. Swap_Init
  1009. ================
  1010. */
  1011. void Swap_Init (void)
  1012. {
  1013.     byte    swaptest[2] = {1,0};
  1014.  
  1015. // set the byte swapping variables in a portable manner    
  1016.     if ( *(short *)swaptest == 1)
  1017.     {
  1018.         bigendien = false;
  1019.         _BigShort = ShortSwap;
  1020.         _LittleShort = ShortNoSwap;
  1021.         _BigLong = LongSwap;
  1022.         _LittleLong = LongNoSwap;
  1023.         _BigFloat = FloatSwap;
  1024.         _LittleFloat = FloatNoSwap;
  1025.     }
  1026.     else
  1027.     {
  1028.         bigendien = true;
  1029.         _BigShort = ShortNoSwap;
  1030.         _LittleShort = ShortSwap;
  1031.         _BigLong = LongNoSwap;
  1032.         _LittleLong = LongSwap;
  1033.         _BigFloat = FloatNoSwap;
  1034.         _LittleFloat = FloatSwap;
  1035.     }
  1036.  
  1037. }
  1038.  
  1039.  
  1040.  
  1041. /*
  1042. ============
  1043. va
  1044.  
  1045. does a varargs printf into a temp buffer, so I don't need to have
  1046. varargs versions of all text functions.
  1047. FIXME: make this buffer size safe someday
  1048. ============
  1049. */
  1050. char    *va(char *format, ...)
  1051. {
  1052.     va_list        argptr;
  1053.     static char        string[1024];
  1054.     
  1055.     va_start (argptr, format);
  1056.     vsprintf (string, format,argptr);
  1057.     va_end (argptr);
  1058.  
  1059.     return string;    
  1060. }
  1061.  
  1062.  
  1063. char    com_token[MAX_TOKEN_CHARS];
  1064.  
  1065. /*
  1066. ==============
  1067. COM_Parse
  1068.  
  1069. Parse a token out of a string
  1070. ==============
  1071. */
  1072. char *COM_Parse (char **data_p)
  1073. {
  1074.     int        c;
  1075.     int        len;
  1076.     char    *data;
  1077.  
  1078.     data = *data_p;
  1079.     len = 0;
  1080.     com_token[0] = 0;
  1081.     
  1082.     if (!data)
  1083.     {
  1084.         *data_p = NULL;
  1085.         return "";
  1086.     }
  1087.         
  1088. // skip whitespace
  1089. skipwhite:
  1090.     while ( (c = *data) <= ' ')
  1091.     {
  1092.         if (c == 0)
  1093.         {
  1094.             *data_p = NULL;
  1095.             return "";
  1096.         }
  1097.         data++;
  1098.     }
  1099.     
  1100. // skip // comments
  1101.     if (c=='/' && data[1] == '/')
  1102.     {
  1103.         while (*data && *data != '\n')
  1104.             data++;
  1105.         goto skipwhite;
  1106.     }
  1107.     
  1108.  
  1109. // handle quoted strings specially
  1110.     if (c == '\"')
  1111.     {
  1112.         data++;
  1113.         while (1)
  1114.         {
  1115.             c = *data++;
  1116.             if (c=='\"' || !c)
  1117.             {
  1118.                 com_token[len] = 0;
  1119.                 *data_p = data;
  1120.                 return com_token;
  1121.             }
  1122.             if (len < MAX_TOKEN_CHARS)
  1123.             {
  1124.                 com_token[len] = c;
  1125.                 len++;
  1126.             }
  1127.         }
  1128.     }
  1129.  
  1130. // parse a regular word
  1131.     do
  1132.     {
  1133.         if (len < MAX_TOKEN_CHARS)
  1134.         {
  1135.             com_token[len] = c;
  1136.             len++;
  1137.         }
  1138.         data++;
  1139.         c = *data;
  1140.     } while (c>32);
  1141.  
  1142.     if (len == MAX_TOKEN_CHARS)
  1143.     {
  1144. //        Com_Printf ("Token exceeded %i chars, discarded.\n", MAX_TOKEN_CHARS);
  1145.         len = 0;
  1146.     }
  1147.     com_token[len] = 0;
  1148.  
  1149.     *data_p = data;
  1150.     return com_token;
  1151. }
  1152.  
  1153.  
  1154. /*
  1155. ===============
  1156. Com_PageInMemory
  1157.  
  1158. ===============
  1159. */
  1160. int    paged_total;
  1161.  
  1162. void Com_PageInMemory (byte *buffer, int size)
  1163. {
  1164.     int        i;
  1165.  
  1166.     for (i=size-1 ; i>0 ; i-=4096)
  1167.         paged_total += buffer[i];
  1168. }
  1169.  
  1170.  
  1171.  
  1172. /*
  1173. ============================================================================
  1174.  
  1175.                     LIBRARY REPLACEMENT FUNCTIONS
  1176.  
  1177. ============================================================================
  1178. */
  1179.  
  1180. // FIXME: replace all Q_stricmp with Q_strcasecmp
  1181. int Q_stricmp (char *s1, char *s2)
  1182. {
  1183. #if defined(WIN32)
  1184.     return _stricmp (s1, s2);
  1185. #else
  1186.     return strcasecmp (s1, s2);
  1187. #endif
  1188. }
  1189.  
  1190.  
  1191. int Q_strncasecmp (char *s1, char *s2, int n)
  1192. {
  1193.     int        c1, c2;
  1194.     
  1195.     do
  1196.     {
  1197.         c1 = *s1++;
  1198.         c2 = *s2++;
  1199.  
  1200.         if (!n--)
  1201.             return 0;        // strings are equal until end point
  1202.         
  1203.         if (c1 != c2)
  1204.         {
  1205.             if (c1 >= 'a' && c1 <= 'z')
  1206.                 c1 -= ('a' - 'A');
  1207.             if (c2 >= 'a' && c2 <= 'z')
  1208.                 c2 -= ('a' - 'A');
  1209.             if (c1 != c2)
  1210.                 return -1;        // strings not equal
  1211.         }
  1212.     } while (c1);
  1213.     
  1214.     return 0;        // strings are equal
  1215. }
  1216.  
  1217. int Q_strcasecmp (char *s1, char *s2)
  1218. {
  1219.     return Q_strncasecmp (s1, s2, 99999);
  1220. }
  1221.  
  1222.  
  1223.  
  1224. void Com_sprintf (char *dest, int size, char *fmt, ...)
  1225. {
  1226.     int        len;
  1227.     va_list        argptr;
  1228.     char    bigbuffer[0x10000];
  1229.  
  1230.     va_start (argptr,fmt);
  1231.     len = vsprintf (bigbuffer,fmt,argptr);
  1232.     va_end (argptr);
  1233.     if (len >= size)
  1234.         Com_Printf ("Com_sprintf: overflow of %i in %i\n", len, size);
  1235.     strncpy (dest, bigbuffer, size-1);
  1236. }
  1237.  
  1238. /*
  1239. =====================================================================
  1240.  
  1241.   INFO STRINGS
  1242.  
  1243. =====================================================================
  1244. */
  1245.  
  1246. /*
  1247. ===============
  1248. Info_ValueForKey
  1249.  
  1250. Searches the string for the given
  1251. key and returns the associated value, or an empty string.
  1252. ===============
  1253. */
  1254. char *Info_ValueForKey (char *s, char *key)
  1255. {
  1256.     char    pkey[512];
  1257.     static    char value[2][512];    // use two buffers so compares
  1258.                                 // work without stomping on each other
  1259.     static    int    valueindex;
  1260.     char    *o;
  1261.     
  1262.     valueindex ^= 1;
  1263.     if (*s == '\\')
  1264.         s++;
  1265.     while (1)
  1266.     {
  1267.         o = pkey;
  1268.         while (*s != '\\')
  1269.         {
  1270.             if (!*s)
  1271.                 return "";
  1272.             *o++ = *s++;
  1273.         }
  1274.         *o = 0;
  1275.         s++;
  1276.  
  1277.         o = value[valueindex];
  1278.  
  1279.         while (*s != '\\' && *s)
  1280.         {
  1281.             if (!*s)
  1282.                 return "";
  1283.             *o++ = *s++;
  1284.         }
  1285.         *o = 0;
  1286.  
  1287.         if (!strcmp (key, pkey) )
  1288.             return value[valueindex];
  1289.  
  1290.         if (!*s)
  1291.             return "";
  1292.         s++;
  1293.     }
  1294. }
  1295.  
  1296. void Info_RemoveKey (char *s, char *key)
  1297. {
  1298.     char    *start;
  1299.     char    pkey[512];
  1300.     char    value[512];
  1301.     char    *o;
  1302.  
  1303.     if (strstr (key, "\\"))
  1304.     {
  1305. //        Com_Printf ("Can't use a key with a \\\n");
  1306.         return;
  1307.     }
  1308.  
  1309.     while (1)
  1310.     {
  1311.         start = s;
  1312.         if (*s == '\\')
  1313.             s++;
  1314.         o = pkey;
  1315.         while (*s != '\\')
  1316.         {
  1317.             if (!*s)
  1318.                 return;
  1319.             *o++ = *s++;
  1320.         }
  1321.         *o = 0;
  1322.         s++;
  1323.  
  1324.         o = value;
  1325.         while (*s != '\\' && *s)
  1326.         {
  1327.             if (!*s)
  1328.                 return;
  1329.             *o++ = *s++;
  1330.         }
  1331.         *o = 0;
  1332.  
  1333.         if (!strcmp (key, pkey) )
  1334.         {
  1335.             strcpy (start, s);    // remove this part
  1336.             return;
  1337.         }
  1338.  
  1339.         if (!*s)
  1340.             return;
  1341.     }
  1342.  
  1343. }
  1344.  
  1345.  
  1346. /*
  1347. ==================
  1348. Info_Validate
  1349.  
  1350. Some characters are illegal in info strings because they
  1351. can mess up the server's parsing
  1352. ==================
  1353. */
  1354. qboolean Info_Validate (char *s)
  1355. {
  1356.     if (strstr (s, "\""))
  1357.         return false;
  1358.     if (strstr (s, ";"))
  1359.         return false;
  1360.     return true;
  1361. }
  1362.  
  1363. void Info_SetValueForKey (char *s, char *key, char *value)
  1364. {
  1365.     char    newi[MAX_INFO_STRING], *v;
  1366.     int        c;
  1367.     int        maxsize = MAX_INFO_STRING;
  1368.  
  1369.     if (strstr (key, "\\") || strstr (value, "\\") )
  1370.     {
  1371.         Com_Printf ("Can't use keys or values with a \\\n");
  1372.         return;
  1373.     }
  1374.  
  1375.     if (strstr (key, ";") )
  1376.     {
  1377.         Com_Printf ("Can't use keys or values with a semicolon\n");
  1378.         return;
  1379.     }
  1380.  
  1381.     if (strstr (key, "\"") || strstr (value, "\"") )
  1382.     {
  1383.         Com_Printf ("Can't use keys or values with a \"\n");
  1384.         return;
  1385.     }
  1386.  
  1387.     if (strlen(key) > MAX_INFO_KEY-1 || strlen(value) > MAX_INFO_KEY-1)
  1388.     {
  1389.         Com_Printf ("Keys and values must be < 64 characters.\n");
  1390.         return;
  1391.     }
  1392.     Info_RemoveKey (s, key);
  1393.     if (!value || !strlen(value))
  1394.         return;
  1395.  
  1396.     Com_sprintf (newi, sizeof(newi), "\\%s\\%s", key, value);
  1397.  
  1398.     if (strlen(newi) + strlen(s) > maxsize)
  1399.     {
  1400.         Com_Printf ("Info string length exceeded\n");
  1401.         return;
  1402.     }
  1403.  
  1404.     // only copy ascii values
  1405.     s += strlen(s);
  1406.     v = newi;
  1407.     while (*v)
  1408.     {
  1409.         c = *v++;
  1410.         c &= 127;        // strip high bits
  1411.         if (c >= 32 && c < 127)
  1412.             *s++ = c;
  1413.     }
  1414.     *s = 0;
  1415. }
  1416.  
  1417. //====================================================================
  1418.  
  1419.  
  1420.